/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable no-unused-vars */
/**
 * @description: 用户管理
 * @author: Daniel
 * @update: 2022/1/16
 */
import React, { useEffect, useCallback } from 'react'
import {
  Grid,
  Box,
  TextField,
  Button,
  IconButton,
  Switch,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogContentText,
  DialogActions,
  Snackbar,
  Collapse,
} from '@material-ui/core'
import { makeStyles, withStyles } from '@material-ui/core/styles'
import SearchIcon from '@material-ui/icons/Search'
import DeleteIcon from '@material-ui/icons/Delete'
import AddIcon from '@material-ui/icons/Add'
import SyncRoundedIcon from '@material-ui/icons/SyncRounded'
import EditIcon from '@material-ui/icons/Edit'
import CloudDownloadIcon from '@material-ui/icons/CloudDownload'
import CloudUploadIcon from '@material-ui/icons/CloudUpload'
import { NewDataGrid, Tree, HomeSelect, DialogAddAndEdit } from '@/components'
import { treeselect, list, user, userDisable, userSex, userRoles, userEdit, userDelete } from '@/apis/Home'
import MuiAlert from '@material-ui/lab/Alert'
import Slide from '@material-ui/core/Slide'
import downloadFile from '@/utils/download-file-with-progress'

function Alert(props) {
  return <MuiAlert elevation={6} variant='filled' {...props} />
}

const Transition = React.forwardRef(function Transition(props, ref) {
  return <Slide direction='up' ref={ref} {...props} />
})

const useStyles = makeStyles((theme) => ({
  container: {
    width: '100%',
  },
  threeLeft: { width: '17%', height: 'calc(100vh - 95px)', minHeight: '605px', overflowY: 'auto' },
  bodyRight: {
    flex: 1,
    height: 'calc(100vh - 95px)',
    minHeight: '605px',
    overflowY: 'auto',
  },
  button_add: {
    color: '#1890ff',
    background: '#e8f4ff',
    borderColor: '#a3d3ff',
    padding: '7px 15px',
    fontSize: '12px',
    borderRadius: '3px',
    margin: '0 0 10px 10px',
    '&:hover': {
      background: '#1890ff',
      borderColor: '#1890ff',
      color: '#fff',
    },
  },
  button_revamp: {
    color: '#71e2a3',
    backgroundColor: '#e7faf0',
    borderColor: '#d0f5e0',
    padding: '7px 15px',
    fontSize: '12px',
    borderRadius: '3px',
    margin: '0 0 10px 10px',
    '&:hover': {
      background: '#13ce66',
      borderColor: '#13ce66',
      color: '#fff',
    },
  },
  button_delet: {
    color: '#ff4949',
    background: '#ffeded',
    borderColor: '#ffb6b6',
    padding: '7px 15px',
    fontSize: '12px',
    borderRadius: '3px',
    margin: '0 0 10px 10px',
    '&:hover': {
      background: '#ff4949',
      borderColor: '#ff4949',
      color: '#fff',
    },
  },
  button_to_lead: {
    color: '#909399',
    background: '#f4f4f5',
    borderColor: '#d3d4d6',
    padding: '7px 15px',
    fontSize: '12px',
    borderRadius: '3px',
    margin: '0 0 10px 10px',
    '&:hover': {
      background: '#909399',
      borderColor: '#909399',
      color: '#fff',
    },
  },
  button_derive: {
    color: '#ffba00',
    background: '#fff8e6',
    borderColor: '#ffe399',
    padding: '7px 15px',
    fontSize: '12px',
    borderRadius: '3px',
    margin: '0 0 10px 10px',
    '&:hover': {
      background: '#ffba00',
      borderColor: '#ffba00',
      color: '#fff',
    },
  },
}))

const Index = () => {
  const classes = useStyles()
  const [selectedDate, setSelectedDate] = React.useState()
  const [treeDatas, setTreeDatas] = React.useState([]) //组织数据
  const [treeDialogDatas, setTreeDialogDatas] = React.useState([]) //新增编辑组织数据
  const [listDatas, setListDatas] = React.useState([]) //列表数据
  const [count, setCount] = React.useState(0) //列表页数总数
  const [pageNum, setPageNum] = React.useState(1) //列表页
  const [deptId, setDeptId] = React.useState('') //列表页
  const [open, setOpen] = React.useState(false) //新增编辑弹框
  const [openWrin, setOpenWrin] = React.useState(false) //警告弹框
  const [showPassword, setShowPassword] = React.useState(false) //显示密码
  const [snackbar, setSnackbar] = React.useState({ open: false, name: '演示模式，不允许操作', type: '' }) //提示
  const [dialogType, setDialogType] = React.useState({ type: 'add', title: '' }) //弹窗类型
  const [selection, setSelection] = React.useState([]) //多选列表
  const [screen, setScreen] = React.useState(true) //筛选条件收缩
  const [disable, setDisable] = React.useState([]) //状态类型
  const [sexList, setSexList] = React.useState([]) //性别类型
  const [postsList, setPostsList] = React.useState([]) //角色类型
  const [rolesList, setRolesList] = React.useState([]) //权限类型
  const [deleteId, setDeleteId] = React.useState('') //删除指定ID
  const [searchList, setSearchList] = React.useState({
    userName: '',
    phonenumber: '',
    status: '',
  }) //列表搜索
  const [dialogData, setDialogData] = React.useState({
    nickName: '',
    deptId: null,
    phonenumber: '',
    email: '',
    password: '123456',
    userName: '',
    sex: '',
    status: '0',
    postIds: [],
    roleIds: [],
    remark: '',
  }) //列表数据

  /**
   * @description: 关闭提示
   */
  const onSnackbarClose = () => {
    setSnackbar({ open: false, name: '', type: '' })
  }

  /**
   * @description: 显示密码
   */
  const handleClickShowPassword = () => {
    setShowPassword(!showPassword)
  }

  const handleMouseDownPassword = (event) => {
    event.preventDefault()
  }

  /**
   * @description: 控制提示
   */
  const onDialogOpen = (value) => {
    setOpen(value)
  }

  /**
   * @description: 控制警告提示
   */
  const onDialogWrinOpen = (value) => {
    setOpenWrin(value)
  }

  /**
   * @description: 时间
   */
  const handleDateChange = (date) => {
    setSelectedDate(date)
  }

  /**
   * @description: 翻页事件
   */
  const onChangePage = useCallback(
    (event, page) => {
      setPageNum(page)
      onList({
        pageNum: page,
        deptId: deptId,
      })
    },
    [deptId]
  )

  /**
   * @description: 列表多选事件
   */
  const onSelectionModelChange = (list) => {
    setSelection(list)
  }

  /**
   * @description: 点击组织事件
   */
  const onChangeDeptId = (event, value) => {
    console.log('value', value)
    setDeptId(value)
    onList({
      pageNum: pageNum,
      deptId: value,
    })
  }

  /**
   * @description: 更新列表
   */
  const onList = async (params) => {
    const res = await list({ ...searchList, ...params })
    const { rows, total } = res
    if (res && Array.isArray(rows)) {
      console.log('rows', rows)
      setListDatas(rows.map((v) => ({ ...v, id: v.userId })))
      const count = total % 5 > 0 ? parseInt(total / 5) + 1 : total / 5
      setCount(count)
    }
  }

  /**
   * @description: 新增或修改
   */
  const onAddUser = useCallback(async () => {
    onDialogOpen(false)
    console.log('dialogType.type', dialogType.type)
    if (dialogType.type === 'add') {
      const params = { ...dialogData, deptId: dialogData.deptId.id }
      const res = await user(params)
      if (res) {
        // onDialogOpen(false)
        info()
        setSnackbar({ open: true, name: '新增成功', type: 'success' })
      } else {
        setSnackbar({ open: true, name: '新增失败', type: 'warning' })
      }
    } else {
      console.log('dialogType.type2', dialogType.type)
      const params = { ...dialogData, deptId: dialogData.deptId.id, add: false, edit: true }
      const res = await userEdit(params)
      if (res) {
        // onDialogOpen(false)
        info()
        setSnackbar({ open: true, name: '修改完成', type: 'success' })
      } else {
        setSnackbar({ open: true, name: '修改失败', type: 'warning' })
      }
    }
  }, [dialogData])

  /**
   * @description: 转化数据
   */
  const toTreeData = useCallback((item) => {
    if (item.children) {
      return { ...item, id: item.id + '', children: item.children.map((v) => toTreeData(v)) }
    } else {
      return { ...item, id: item.id + '' }
    }
  })

  /**
   * @description: 弹框组织转化数据
   */
  const toTreeDialogData = (list) => {
    return list.reduce((prev, cur) => {
      if (cur.children) {
        const { children, ...props } = cur
        return [...prev, props, ...toTreeDialogData(children)]
      } else {
        return [...prev, cur]
      }
    }, [])
  }

  /**
   * @description: 添加用户数据
   */
  const onAddItem = () => {
    setDialogType({ type: 'add', title: '添加用户' })
    setTimeout(() => {
      setDialogData({
        nickName: '',
        phonenumber: '',
        email: '',
        password: '',
        userName: '',
        sex: '',
        status: '',
        postIds: [],
        roleIds: [],
        remark: '',
        deptId: '',
        userId: '',
      })
      setTimeout(() => {
        onDialogOpen(true)
      })
    })
  }

  /**
   * @description: 编辑用户数据
   */
  const onEditItem = ({ data = false }) => {
    setDialogType({ type: 'edit', title: '修改用户' })
    let item = data ? data : listDatas.filter((v) => v.id === selection[0])[0]
    setDialogData({
      ...item,
      nickName: item.nickName,
      phonenumber: item.phonenumber,
      email: item.email,
      password: '',
      sex: item.sex,
      status: item.status,
      postIds: item.postIds || [],
      roleIds: item.roleIds || [],
      remark: item.remark,
      deptId:
        treeDialogDatas.filter((v) => v.id === item?.deptId.toString()).length > 0
          ? treeDialogDatas.filter((v) => v.id === item?.deptId.toString())[0]
          : '',
      userId: item.userId,
    })
    setTimeout(() => {
      onDialogOpen(true)
    })
  }

  /**
   * @description: 初始化事件
   */
  const info = async () => {
    setPageNum(1)
    const res = await treeselect()
    if (res) {
      const { data } = res
      const tree = await data.map((v) => toTreeData(v))
      setTreeDatas(tree)
      console.log('toTreeDialogData(tree)', toTreeDialogData(tree))
      setTreeDialogDatas(toTreeDialogData(tree))
      if (Array.isArray(data) && data.length > 0) {
        setDeptId(data[0].id)
        const params = {
          ...searchList,
          pageNum: 1,
          deptId: data[0].id,
        }
        const res = await list(params)
        const { rows, total } = res
        if (res && Array.isArray(rows)) {
          console.log('rows', rows)
          setListDatas(rows.map((v) => ({ ...v, id: v.userId })))
          const count = total % 5 > 0 ? parseInt(total / 5) + 1 : total / 5
          setCount(count)
        }
      }
    }
    const resD = await userDisable()
    if (resD && resD.data) {
      setDisable(resD.data)
    }
    const resS = await userSex()
    if (resS && resS.data) {
      setSexList(resS.data)
    }
    const resR = await userRoles()
    if (resR) {
      setPostsList(resR.posts)
      setRolesList(resR.roles)
    }
  }

  useEffect(() => {
    info()
  }, [])

  /**
   * @description: 用户列表头部数据
   */
  const columns = [
    { field: 'userId', headerName: '用户编号', width: 90 },
    {
      field: 'userName',
      headerName: '用户名称',
      width: 150,
    },
    {
      field: 'nickName',
      headerName: '用户昵称',
      width: 150,
    },
    {
      field: 'dept',
      headerName: '部门',
      width: 150,
      renderCell: (params) => {
        return <Box>{params.getValue(params.id, 'dept')?.deptName}</Box>
      },
    },
    {
      field: 'phonenumber',
      headerName: '手机号码',
      width: 150,
    },
    {
      field: 'status',
      headerName: '状态',
      width: 110,
      renderCell: (params) => {
        return (
          <Switch
            checked={Boolean(params.getValue(params.id, 'status'))}
            inputProps={{ 'aria-label': 'secondary checkbox' }}
          />
        )
      },
    },
    {
      field: 'createTime',
      headerName: '创建时间',
      width: 150,
    },
    {
      field: 'add',
      headerName: '操作',
      sortable: false,
      width: 160,
      renderCell: (params) => {
        return (
          <Box>
            <Button
              onClick={() => {
                onEditItem(params.row)
              }}
              component='span'
              color='primary'
              size='small'
              startIcon={<EditIcon />}
            >
              修改
            </Button>
            <Button
              onClick={() => {
                setDeleteId(params.getValue(params.id, 'id'))
                onDialogWrinOpen(true)
              }}
              component='span'
              color='secondary'
              size='small'
              startIcon={<DeleteIcon />}
            >
              删除
            </Button>
          </Box>
        )
      },
    },
  ]

  return (
    <Box className={classes.container}>
      <Grid className={classes.main} container direction='row'>
        <Box className={classes.threeLeft}>
          <Box m={'15px'}>
            <TextField
              id='outlined-start-adornment'
              size='small'
              InputProps={{
                startAdornment: <SearchIcon />,
              }}
              variant='outlined'
            />

            <Tree datas={treeDatas} onChange={onChangeDeptId} />
          </Box>
        </Box>
        <Box className={classes.bodyRight}>
          <Box m={'15px 15px 15px 0'}>
            <Collapse in={screen}>
              <HomeSelect
                searchList={searchList}
                setSearchList={setSearchList}
                disable={disable}
                selectedDate={selectedDate}
                handleDateChange={handleDateChange}
                deptId={deptId}
                info={info}
                onList={onList}
                setPageNum={setPageNum}
              />
            </Collapse>

            <Grid container direction='row' justifyContent='space-between' alignItems='center'>
              <Box>
                <Button variant='contained' onClick={onAddItem} className={classes.button_add} startIcon={<AddIcon />}>
                  新增
                </Button>
                <Button
                  disabled={selection.length === 1 ? false : true}
                  onClick={onEditItem}
                  variant='contained'
                  className={classes.button_revamp}
                  startIcon={<EditIcon />}
                >
                  修改
                </Button>
                <Button
                  disabled={selection.length > 0 ? false : true}
                  variant='contained'
                  className={classes.button_delet}
                  onClick={() => onDialogWrinOpen(true)}
                  startIcon={<DeleteIcon />}
                >
                  删除
                </Button>
                <input accept='image/*' style={{ display: 'none' }} id='contained-button-file' multiple type='file' />
                <label htmlFor='contained-button-file'>
                  <Button
                    variant='contained'
                    className={classes.button_to_lead}
                    component='span'
                    startIcon={<CloudUploadIcon />}
                  >
                    导入
                  </Button>
                </label>
                <Button
                  variant='contained'
                  onClick={() =>
                    downloadFile({
                      // 假链接测试下载
                      axiosConfig: {
                        method: 'get',
                        url: 'http://img.wangxiao.cn/files/RemoteFiles/20140420/095185001.jpg',
                      },
                      downloadName: 'cs123.jpg',
                    })
                  }
                  className={classes.button_derive}
                  startIcon={<CloudDownloadIcon />}
                >
                  导出
                </Button>
              </Box>
              <Box>
                <IconButton
                  size='medium'
                  style={{ marginRight: '5px' }}
                  onClick={() => setScreen(!screen)}
                  aria-label='add an alarm'
                >
                  <SearchIcon />
                </IconButton>
                <IconButton size='medium' onClick={info} aria-label='add an alarm'>
                  <SyncRoundedIcon />
                </IconButton>
              </Box>
            </Grid>
            <Box m={'10px'}>
              <NewDataGrid
                datas={listDatas}
                columns={columns}
                count={count}
                pageNum={pageNum}
                onChange={onChangePage}
                onSelectionModelChange={onSelectionModelChange}
              />
            </Box>
          </Box>
        </Box>
      </Grid>
      <DialogAddAndEdit
        open={open}
        onDialogOpen={onDialogOpen}
        dialogType={dialogType}
        dialogData={dialogData}
        setDialogData={setDialogData}
        treeDialogDatas={treeDialogDatas}
        showPassword={showPassword}
        handleClickShowPassword={handleClickShowPassword}
        handleMouseDownPassword={handleMouseDownPassword}
        sexList={sexList}
        postsList={postsList}
        rolesList={rolesList}
        onAddUser={onAddUser}
        disable={disable}
      />

      <Dialog
        open={openWrin}
        TransitionComponent={Transition}
        keepMounted
        onClose={() => {
          onDialogWrinOpen(false)
          setDeleteId('')
        }}
        aria-labelledby='alert-dialog-slide-title'
        aria-describedby='alert-dialog-slide-description'
      >
        <DialogTitle id='alert-dialog-slide-title'>{'提示'}</DialogTitle>
        <DialogContent>
          <DialogContentText className={classes.dialog_text} id='alert-dialog-slide-description'>
            是否确认删除用户的数据项？
          </DialogContentText>
        </DialogContent>
        <DialogActions>
          <Button
            onClick={() => {
              onDialogWrinOpen(false)
              setDeleteId('')
            }}
            variant='outlined'
          >
            取消
          </Button>
          <Button
            onClick={async () => {
              onDialogWrinOpen(false)
              const res = await userDelete(deleteId || selection.join())
              setDeleteId('')
              if (res) {
                info()
                setSnackbar({ open: true, name: '删除成功', type: 'success' })
              } else {
                setSnackbar({ open: true, name: '删除失败', type: 'warning' })
              }
            }}
            variant='contained'
            color='primary'
          >
            确定
          </Button>
        </DialogActions>
      </Dialog>
      <Snackbar
        anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
        open={snackbar.open}
        autoHideDuration={2000}
        onClose={onSnackbarClose}
      >
        <Alert onClose={onSnackbarClose} severity={snackbar.type}>
          {snackbar.name}
        </Alert>
      </Snackbar>
    </Box>
  )
}

export default Index
